package org.btik.light.mobile.server;

import org.btik.light.meta.Dev;
import org.btik.light.meta.DevMo;
import org.btik.light.meta.base.CmdCode;
import org.btik.light.meta.base.Command;
import org.btik.light.mobile.platform.thread.BaseLoopControllableThread;
import org.btik.light.mobile.platform.thread.Controllable;
import org.btik.light.mobile.platform.thread.ShutDownCmd;
import org.btik.light.mobile.platform.util.ByteBuffer;


import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;

/***
 *与设备报文交互
 * */
public class MsgCenter implements Controllable {

    private final LinkedBlockingQueue<Command> sendQueue = new LinkedBlockingQueue<>();

    private final LinkedBlockingQueue<Runnable> events = new LinkedBlockingQueue<>();

    private Sender sender;

    private DisPachter disPachter;

    private static MsgCenter instance;

    private DevAccessServer devAccessServer;

    public void setDevAccessServer(DevAccessServer devAccessServer) {
        this.devAccessServer = devAccessServer;
    }

    private final Set<DevEventListener> devEventListeners = new HashSet<>();

    void onDevConnect(DevMo devMo) {
        events.add(() -> {
            for (DevEventListener devEventListener : devEventListeners) {
                devEventListener.onDevConnect(devMo);
            }
        });
    }

    public synchronized void regDevListener(DevEventListener devEventListener) {
        devEventListeners.add(devEventListener);
    }

    class DisPachter extends BaseLoopControllableThread {

        @Override
        protected boolean loop() {
            try {
                Runnable take = events.take();
                if (take instanceof ShutDownCmd) {
                    return false;
                }
                take.run();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return true;
        }

        @Override
        public void shutdown(String msg) {
            events.add(ShutDownCmd.getInstance());
            super.shutdown(msg);
        }
    }

    class Sender extends BaseLoopControllableThread {

        @Override
        protected boolean loop() {
            try {
                Command cmd = sendQueue.take();
                if (cmd instanceof ShutDownCmd) {
                    return false;
                }
                Dev dev = devAccessServer.getDev(cmd.getTarget());
                if (dev != null)
                    dev.sendCmdOrMsg(cmd);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return true;
        }

        @Override
        public void shutdown(String msg) {
            sendQueue.add(ShutDownCmd.getInstance());
            super.shutdown(msg);
        }
    }

    @Override
    public void start() {
        sender = new Sender();
        sender.start();
        disPachter = new DisPachter();
        disPachter.start();
    }

    @Override
    public void shutdown(String msg) {
        sender.shutdown(msg);
        disPachter.shutdown(msg);
    }

    public MsgCenter() {
        MsgCenter.instance = this;
    }

    public void sendCmd(Command command) {
        sendQueue.add(command);
    }

}
